home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
wasm223.zip
/
AUTOPARK.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-05-04
|
17KB
|
529 lines
;********************************************************
; AutoPark by Eric Tauck
;
; This TSR parks a hard disk in the background after
; a specified period of disk inactivity. AutoPark may
; be installed multiple times for multiple hard disks.
; AutoPark does not check to see if a drive is valid.
;
; Usage: AUTOPARK drive time install
; AUTOPARK park
; AUTOPARK PARK park
; AUTOPARK ENABLE enable
; AUTOPARK DISABLE disable
;
; drive = hard disk drive letter
; time = minutes of inactivity
;
; The disable, enable, and park options affect all
; resident copies of AutoPark.
;
; AutoPark can interfere with applications that access
; the hard disk at a low level. A new feature of version
; 2.00 is the ability to enable and disable all resident
; copies of AutoPark, and I recommend using this feature
; for any applications that reformat, defragment, or
; continuously read or write to the hard disk (like a
; backup program).
;
; AutoPark uses a special interrupt to communicate with
; resident copies of AutoPark. This interrupt may be
; used by other TSR's if they are installed BEFORE
; AutoPark, or by regular applications as long as the
; interrupt is restored when the application terminates.
; The interrupt is only necessary perform a forced park,
; enable, or disable resident copies of AutoPark. The
; interrupt (EQUated at the start of the code) can be
; changed to any non-reserved interrupt: 60 to 66 or F1
; to FF.
;
; Note: I looked at several other hard disk parking
; utilities in order to determine the the best way to
; park a hard disk. This program appears to work on my
; computer, but I don't guarantee it will work on all
; computers.
;
; This code is written for WASM and requires several of
; the WASM library files.
;
;--------------------------------------------------------
;
; Version 1.10
;
; The disk handler now checks to see if the drive to
; be parked is being accessed. Previously, any
; INT 13 call was assumed to unpark the drive.
;
; Version 1.20
;
; The disk handler now prevents a park attempt when
; accessing another drive (this caused AutoPark to
; crash the system). The INT 1C handler has also been
; rewritten.
;
; Version 1.21
;
; The relocation address is changed to 5CH (from 80H),
; which overwrites the PSP FCB's and shrinks AutoPark's
; resident size a little.
;
; Version 1.22
;
; Slightly changed the messages.
;
; Version 2.00
;
; Added park, disable, and enable options. A colon is
; allowed in the drive name. The interrupt handlers
; have been rewritten to make the code a little smaller
; and faster.
;
; Version 2.01
;
; All disks are parked if installed and no command line
; options.
C_INT EQU 0F7H ;chain interrupt, can be changed
jmp Install ;goto installation
CODE_BEGIN ;start of code to relocate
NEWADDR EQU 5CH ;new address
RELOC EQU $ - NEWADDR ;displacement
drive DB ? ;drive to park
time DW ? ;timer setting
count DW ? ;timer count
block DB 0 ;block (reentrancy) flag
old13 LABEL DWORD ;original interrupt 13H
DW ?
DW ?
old1C LABEL DWORD ;original interrupt 1CH
DW ?
DW ?
chain LABEL DWORD ;chain interrupt (for resident AutoParks)
DW ?
DW ?
;--- chain the chain interrupt (for other applications using this interrupt)
chain_jump
seg cs
jmp chain ;jump to previous handler
;========================================
; Disk handler.
Disk PROC FAR
jmps disk1 ;change offset to 0 to ENABLE
seg cs
cmp dl, drive - RELOC ;check if drive to park
jne disk1 ;skip if not
seg cs
push time - RELOC
seg cs
pop count - RELOC ;reset timer
disk1 seg cs
inc block - RELOC
pushf
seg cs
call old13 - RELOC ;call original
seg cs
dec block - RELOC
ret 2
ENDP
;========================================
; Timer handler.
Timer PROC FAR
jmps timer1 ;change offset to 0 to ENABLE
seg cs
cmp count - RELOC, 0 ;check if count zero
je timer1
seg cs
dec count - RELOC ;decrement count
jnz timer1
seg cs
cmp block - RELOC, 0 ;check if blocked
je Park
seg cs
inc count - RELOC ;reset count to one
timer1 seg cs
jmp old1C - RELOC ;chain to original
;----------------------------------------
; Park the disk drive.
Park sti
push ax
push bx
push cx
push dx
mov al, 20H ;@@@ TIMEPARK does this @@@
out 20H, al ;
mov ah, 8 ;read drive parameters
seg cs
mov dl, drive - RELOC ;drive number
pushf
seg cs
call old13 - RELOC ;execute
; and cl, 0C0H ;@@@ Northgate PARK does this @@@
; inc cl ;
inc ch ;cylinder after last cylinder
jnz park1 ;skip if no carry
add cl, 40H ;carry
park1 mov ah, 0CH ;seek function
; mov al, 1 ;@@@ TIMEPARK does this @@@
seg cs
mov dl, drive - RELOC ;drive
sub dh, dh ;head zero
pushf
seg cs
call old13 - RELOC ;execute
pop dx
pop cx
pop bx
pop ax
jmps timer1
ParkX ;end of Park
ENDP
CODE_END
;========================================
; Install.
;--- installation data
banner DB 10,13, 'AutoPark Version 2.01 Eric Tauck', 0
smess1 DB 'Drive C: will be parked after ', 0
smess2 DB ' minute(s)', 0
optmes1 DB 'ENABLE',0
optmes2 DB 'DISABLE',0
optmes3 DB 'PARK',0
hmess DB 10,13
DB 'Usage: AUTOPARK drive time install',13,10
DB ' AUTOPARK PARK park',13,10
DB ' AUTOPARK ENABLE enable',13,10
DB ' AUTOPARK DISABLE disable',13,10
DB 10,13
DB ' drive = hard disk drive letter',13,10
DB ' time = minutes of inactivity'
DB 0
emess DB 'Error in parameters, run "AUTOPARK ?" for help', 0
rmess1 DB 'Cannot enable, AutoPark is not resident',0
rmess2 DB 'Cannot disable, AutoPark is not resident',0
rmess3 DB 'Hard disk parking enabled',0
rmess4 DB 'Hard disk parking disabled',0
rmess5 DB 'Cannot park, AutoPark is not resident',0
rmess6 DB 'Parking all hard disks',0
;=== entry point
Install
INCLUDE 'library\case1.asm'
INCLUDE 'library\case2.asm'
INCLUDE 'library\convert.asm'
INCLUDE 'library\message1.asm'
INCLUDE 'library\intr.asm'
INCLUDE 'library\parms.asm'
INCLUDE 'library\string.asm'
jmp inst1 ;skip error and help messages
;--- help
help mov ax, OFFSET hmess
exit call MesPutL
mov ax, 4C00H
int 21H
;--- enable
enable mov ax, OFFSET R_Enable ;enable routine
call Resident ;set resident options
mov ax, OFFSET rmess1
jz error2
mov ax, OFFSET rmess3
jmps exit
;--- disable
disable mov ax, OFFSET R_Disable ;disable routine
call Resident ;set resident options
mov ax, OFFSET rmess2
jz error2
mov ax, OFFSET rmess4
jmps exit
;--- forced park
forced mov ax, OFFSET R_Park ;park routine
call Resident ;set resident options
mov ax, OFFSET rmess5
jz error2
mov ax, OFFSET rmess6
jmps exit
;--- error
error1 mov ax, OFFSET emess
error2 call MesPutL
mov ax, 4CFFH
int 21H
;--- begin installation, show banner
inst1 mov ax, OFFSET banner
call MesPutL
;--- get first option
call ParGet ;get drive
jc forced ;park if no parameter
mov si, ax
cmp BYTE [si], '?' ;check if help request
je help ;jump if so
call StrUpr ;convert to upper case
mov ax, si
mov bx, OFFSET optmes1 ;ENABLE string
call StrCmp ;check if enable
jnc enable
mov ax, si
mov bx, OFFSET optmes2 ;DISABLE string
call StrCmp ;check if disable
jnc disable
mov ax, si
mov bx, OFFSET optmes3 ;PARK string
call StrCmp ;check if disable
jnc forced
mov ax, si
call StrLen ;get length
dec ax ;check if just one character
jz inst2
dec ax ;check if two characters
jnz error1 ;jump if not
cmp BYTE [si+1], ':' ;check if second character is colon
jne error1
inst2 mov al, [si] ;load drive letter
sub al, 'C' ;convert to number, C = 0, D = 1, etc
cmp al, 25 ;check range
ja error1
add smess1 + 6, al ;set drive letter in message
or al, 80H ;must set high bit for parking
mov drive, al ;save it
;--- get timer value
call ParGet ;get time
jc error1 ;jump if none
push ax ;save for display
mov cx, 10 ;base 10
call Str2Num ;convert to number
jc error1 ;jump if bad number
or ax, ax ;check if zero
jz error1
or dx, dx ;check if too big
jnz error1
mov cx, 1092 ;ticks per minute
mul cx ;convert minutes to ticks
or dx, dx ;check if too big
jnz error1 ;jump if so
mov time, ax ;save timer value
mov count, ax ;save current value
;--- display success message
mov ax, OFFSET smess1
call MesPut
pop ax
call MesPut
mov ax, OFFSET smess2
call MesPutL
;--- save old interrupts
mov al, 13H ;disk handler
call IntGet ;get interrupt
mov WORD old13, bx ;save offset
mov WORD old13+2, dx ;save segment
mov al, 1CH ;timer tick
call IntGet ;get interrupt
mov WORD old1C, bx ;save offset
mov WORD old1C+2, dx ;save segment
mov al, C_INT ;chain interrupt
call IntGet ;get interrupt
cmp bx, OFFSET chain_jump - RELOC ;check if same offset
jne inst3
mov ax, cs
cmp dx, ax ;check if same segment
jne inst3
sub bx, bx ;zero offset
mov dx, bx ;zero segment
inst3 mov WORD chain, bx ;save offset
mov WORD chain+2, dx ;save segment
;--- copy code
mov si, OFFSET CODE_BEGIN ;current address
mov di, NEWADDR ;new address
mov cx, OFFSET CODE_END - OFFSET CODE_BEGIN ;bytes of code
cld
rep ;
movsb ;copy code
;--- hook new interrupts
mov al, 13H ;disk handler
mov dx, cs ;segment
mov bx, OFFSET Disk - RELOC ;offset
call IntSet ;set interrupt
mov al, 1CH ;disk handler
mov dx, cs ;segment
mov bx, OFFSET Timer - RELOC ;offset
call IntSet ;set interrupt
mov al, C_INT ;chain interrupt
mov dx, cs ;segment
mov bx, OFFSET chain_jump - RELOC ;offset
call IntSet ;set interrupt
;--- enable the handlers
mov BYTE [OFFSET Disk - RELOC + 1], 0 ;enable disk interrupt
mov BYTE [OFFSET Timer - RELOC + 1], 0 ;enable timer interrupt
;--- release environment
push es
mov ah, 49H ;release function
mov es, [2CH] ;environment segment
int 21H ;execute
mov WORD [2CH], 0 ;zero address
pop es
;--- terminate
mov ax, OFFSET CODE_END - RELOC ;bytes to reserve
mov dx, ax
mov cl, 4 ;bits to shift
shr dx, cl ;convert to paragraph
test ax, 0FH ;check if extra bits
jz inst4 ;skip if not
inc dx ;round paragraph up
inst4 mov ax, 3100H ;TSR with error code 0
int 21H ;execute
;========================================
; Send options to resident AutoParks.
;
; In: AX= resident routine.
;
; Out: ZF= set if no resident AutoParks.
Resident PROC NEAR
push ax
mov al, C_INT ;interrupt
call IntGet ;get segment
pop bp
sub bx, bx ;count instances
or dx, dx ;check if zero (not set
jz resid3
push ds
mov ds, dx ;load segment
jmps resid2
;--- set resident option
resid1 call bp ;call enable/disable
inc bx ;increment pointer
;--- next installation
mov ds, WORD chain - RELOC + 2 ;new segment
;--- check if pointing to resident AutoPark
resid2 mov si, OFFSET Park - RELOC ;potential resident offset
mov di, OFFSET Park ;local offset
mov cx, OFFSET ParkX - OFFSET Park ;bytes to compare
cld
rep
cmpsb ;compare code
je resid1
pop ds
resid3 or bx, bx ;set ZF
ret
ENDP
;========================================
; Resident routines.
;--- disable routine
R_Disable PROC NEAR
seg es
mov al, [OFFSET Disk + 1] ;load enable byte
mov [OFFSET Disk - RELOC + 1], al ;disable disk interrupt
seg es
mov al, [OFFSET Timer + 1] ;load enable byte
mov [OFFSET Timer - RELOC + 1], al ;disable timer interrupt
ret
ENDP
;--- enable routine
R_Enable PROC NEAR
mov BYTE [OFFSET Disk - RELOC + 1], 0 ;enable disk interrupt
mov BYTE [OFFSET Timer - RELOC + 1], 0 ;enable timer interrupt
mov ax, time - RELOC
mov count - RELOC, ax ;reset timer
ret
ENDP
;--- forced park
R_Park PROC NEAR
mov BYTE [OFFSET Disk - RELOC + 1], 0 ;enable disk interrupt
mov BYTE [OFFSET Timer - RELOC + 1], 0 ;enable timer interrupt
mov count - RELOC, 1 ;set timer, one tick
ret
ENDP